﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using SharedLib.WinFormMVCFramework;
using TracyGUI.View.EntryTabs;
using Tracy;
using Tracy.DataModel;

namespace TracyGUI.Controller.EntryTabs
{
    class TagViewController: ControllerBase<ITagView>, IController<ITagView>
    {
        Entry _entry;
        protected override ITagView ResolveView()
        {
            return TracyFacade.Instance.DIContainer.Resolve<ITagView>();
        }

        public TagViewController(Entry entry)
        {
            //View Events
            View.TagAssigning += new EventHandler<SharedLib.GenericEventArgs<Tag>>(View_TagAssigning);
            View.TagRemoving += new EventHandler<SharedLib.GenericEventArgs<Tag>>(View_TagRemoving);
            View.TagUpdating += new EventHandler<SharedLib.DataChangedEventArgs<Tag>>(View_TagUpdating);

            View.WillAddTag += new EventHandler(View_WillAddTag);
            View.WillUpdateTag += new EventHandler<SharedLib.GenericEventArgs<Tag>>(View_WillUpdateTag);
            
            View.CategorySelected += new EventHandler<SharedLib.GenericEventArgs<string>>(View_CategorySelected);

            //Model Events
            TracyFacade.Instance.TagManager.TagAssigned += new EventHandler<SharedLib.EnhancedEventArgs>(TagManager_TagAssigned);
            TracyFacade.Instance.TagManager.TagRemoved += new EventHandler<SharedLib.EnhancedEventArgs>(TagManager_TagRemoved);
            TracyFacade.Instance.TagManager.TagUpdated += new EventHandler<SharedLib.EnhancedEventArgs>(TagManager_TagUpdated);

            //Init
            _entry = entry;
            View.LoadTags(TracyFacade.Instance.TagManager.GetTags(entry));
            View.LoadCategories(TracyFacade.Instance.TagManager.Categories);
        }



        #region View Events
        void View_TagRemoving(object sender, SharedLib.GenericEventArgs<Tag> e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                TracyFacade.Instance.TagManager.RemoveTag(_entry, e.Data);
                View.EndEditTag();
            }, "UI Policy");
        }

        void View_TagAssigning(object sender, SharedLib.GenericEventArgs<Tag> e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                TracyFacade.Instance.TagManager.AssignTag(_entry, e.Data);
                View.EndEditTag();
            }, "UI Policy");
        }

        void View_TagUpdating(object sender, SharedLib.DataChangedEventArgs<Tag> e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                TracyFacade.Instance.TagManager.UpdateTag(_entry, e.OriginalData, e.Data);
                View.EndEditTag();
            }, "UI Policy");
        }

        void View_WillAddTag(object sender, EventArgs e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                string defaultCategory = null;
                List<string> categories = TracyFacade.Instance.TagManager.Categories;
                foreach (string category in categories)
                {
                    bool isCategoryExisting = false;
                    foreach (Tag existingTag in TracyFacade.Instance.TagManager.GetTags(_entry))
                    {
                        if (category == existingTag.Category)
                        {
                            isCategoryExisting = true;
                            break;
                        }
                    }
                    if (!isCategoryExisting)//Select the first non-used category
                    {
                        defaultCategory = category;
                        break;
                    }
                }

                View.BeginAddTag(defaultCategory);
            }, "UI Policy");
        }
        
        void View_WillUpdateTag(object sender, SharedLib.GenericEventArgs<Tag> e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                View.BeginEditTag(e.Data);
            }, "UI Policy");
        }


        void View_CategorySelected(object sender, SharedLib.GenericEventArgs<string> e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                if (!String.IsNullOrEmpty(e.Data)) View.SetRecommendedValues(TracyFacade.Instance.TagManager.GetValues(e.Data));
                else View.SetRecommendedValues(new List<string>());
            }, "UI Policy");
        }
        #endregion

        #region Model Events
        void TagManager_TagAssigned(object sender, SharedLib.EnhancedEventArgs e)
        {
            Entry entry = (Entry) e.Attributes["entry"];
            if (entry.ID == _entry.ID)
            {
                List<Tag> tags = new List<Tag>();
                tags.Add((Tag)e.Attributes["tag"]);
                View.LoadTags(tags, false);
            }
        }

        void TagManager_TagRemoved(object sender, SharedLib.EnhancedEventArgs e)
        {
            Entry entry = (Entry)e.Attributes["entry"];
            if (entry.ID == _entry.ID)
            {
                View.RemoveTag((Tag)e.Attributes["tag"]);
            }
        }
        void TagManager_TagUpdated(object sender, SharedLib.EnhancedEventArgs e)
        {
            Entry entry = (Entry)e.Attributes["entry"];
            if (entry.ID == _entry.ID)
            {
                View.UpdateTag((Tag)e.Attributes["originalTag"], (Tag)e.Attributes["tag"]);
            }
        }
        #endregion
    }
}
